package com.lebang.service.buss;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayFundTransOrderQueryRequest;
import com.alipay.api.request.AlipayFundTransToaccountTransferRequest;
import com.alipay.api.response.AlipayFundTransOrderQueryResponse;
import com.alipay.api.response.AlipayFundTransToaccountTransferResponse;
import com.lebang.common.AliPayConfig.PayConstants;
import com.lebang.component.RedisClient;
import com.lebang.domain.MemberNewTrade;
import com.lebang.entity.RequestHeaders;
import com.lebang.entity.member.LbbMember;
import com.lebang.entity.member.LbbMemberTrade;
import com.lebang.example.LbbMemberTradeExample;
import com.lebang.mapper.*;
import com.lebang.model.MoneyCategory;
import com.lebang.model.Whether;
import com.lebang.model.enums.Booleans;
import com.lebang.model.enums.buss.RewardType;
import com.lebang.model.enums.buss.TradeCategory;
import com.lebang.model.enums.buss.TradeStatus;
import com.lebang.model.vo.buss.AppliesListVo;
import com.lebang.model.vo.buss.AppliesSearchVo;
import com.lebang.model.vo.buss.MemberTradeSearchVo;
import com.lebang.service.MemberWalletService;
import com.lebang.service.RankingService;
import com.lebang.service.WxPayService;
import com.lebang.service.mongodb.IMemberNewTradeMongodb;
import com.lebang.service.rouseday.RouseDayConfigService;
import com.lebangweb.common.TextUtil;
import com.lebangweb.response.Callback;
import com.lebangweb.response.JsonData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

import static com.lebang.model.enums.buss.TradeStatus.*;

@Service
public class MemberTradeService {
    @Autowired
    private MemberNewTradeMapper memberNewTradeMapper;
    private static final Logger log = LoggerFactory.getLogger(MemberTradeService.class);

    @Autowired
    private WalletService walletService;

    @Autowired
    private LbbMemberTradeMapper lbbMemberTradeMapper;
    @Autowired
    private WxPayService wxPayService;
    @Autowired
    private LbbMemberMapper lbbMemberMapper;
    @Autowired
    private RankingService rankingService;

    @Autowired
    private RedisClient redisClient;
    @Autowired
    private IMemberNewTradeMongodb iMemberNewTradeMongodb;
    @Value("${zfb.ALI_URL}")
    private String ALI_URL;
    @Value("${zfb.ALI_APP_ID}")
    private String ALI_APP_ID;
    @Value("${zfb.ALI_PRIVATE_KEY}")
    private String ALI_PRIVATE_KEY;
    @Value("${zfb.ALI_PUBLIC_KEY}")
    private String ALI_PUBLIC_KEY;

    public static final String CATEGORY_KEY="CATEGORY_KEY:";
    @Autowired
    private MemberWalletService memberWalletService;
    @Autowired
    private MemberWalletMapper memberWalletMapper;
    @Autowired
    private RouseDayConfigService rouseDayConfigService;
    @Autowired
    private MemberHeaderHistoryMapper memberHeaderHistoryMapper;

    public Map<String, Object> list(MemberTradeSearchVo vo) {
        Map<String, Object> data = new HashMap<String, Object>(1);
        Integer total = lbbMemberTradeMapper.total(vo);
        List<LbbMemberTrade> rows = lbbMemberTradeMapper.pagging(vo);
        data.put("total", total);
        data.put("rows", rows);
        return data;
    }



    public JsonData updateStatus(Long id, TradeStatus status, String remark, String userid) {
        LbbMemberTrade trade = lbbMemberTradeMapper.selectByPrimaryKey(id);

        if (trade == null) {
            return Callback.fail("error", "未找到数据", null);
        } else {
            if (!trade.getStatus().equals(TradeStatus.Empty)) {
                return Callback.fail("error", "只能审核待审核的数据", null);
            }
            if (null != remark && !"".equals(remark)) {
                trade.setRemark(remark);
            }
            String desc = "";
            if (status.equals(Success)) {
                desc = "您申请的{money}提现审核成功！";
                trade.setCheckStatus(2);
            } else {
                memberWalletService.addFail(trade.getMemberId());
                desc = "您申请的{money}提现审核失败！";
                trade.setStatus(Invalid);
                trade.setCheckStatus(2);
                String money = new BigDecimal(trade.getAmount()).divide(new BigDecimal(100)).setScale(2).toString();
                desc = desc.replace("{money}", money);
                walletService.notice2(trade, "提现通知", desc);
            }
            trade.setChecker(userid);
            lbbMemberTradeMapper.updateByPrimaryKeySelective(trade);
            return Callback.success("200", "操作成功", null);
        }
    }

    public Map<String, Object> historyList(AppliesSearchVo vo) {
        Map<String, Object> data = new HashMap<String, Object>(1);
        Integer total = lbbMemberTradeMapper.totalHistory(vo);
        List<AppliesListVo> rows = lbbMemberTradeMapper.paggingHistory(vo);
        data.put("total", total);
        data.put("rows", rows);
        return data;
    }




    public int insertSelective(LbbMemberTrade trade) {
        trade.setHasDeleted(Booleans.False.name());
        trade.setCreateTime(new Date());
        return lbbMemberTradeMapper.insertSelective(trade);
    }

    /**
     * 微信企业付款
     *
     * @param id
     * @param userid
     * @param mark
     * @return
     */
    public JsonData staffPayByWx(Long id, String userid, String mark) throws InterruptedException {
        LbbMemberTrade trade = lbbMemberTradeMapper.selectByPrimaryKey(id);
        LbbMember member = lbbMemberMapper.getMemberByMemberId(trade.getMemberId());
        if (TextUtil.isEmpty(member.getWeixinName())) {
            return Callback.fail("2004", "转账失败,用户未实名,请让用户在个人资料填上真实姓名");
        }
        if (TextUtil.isEmpty(member.getWxOpenid()) || member.getWxStatus().equals(0)) {
            return Callback.fail("2003", "转账失败,用户微信未绑定!!");
        }

        trade.setRemittance(2);
        trade.setPayStaff(userid);
        trade.setPayType(2);
        trade.setStatus(Success);
        trade.setNote(mark);
        trade.setTradeTime(new Date());

        Map result = wxPayService.weChatTransfer(trade.getTradeNo(), trade.getAmount().toString(), mark, trade.getIpAddr(), member.getWxOpenid(), member.getWeixinName());
        if ("SUCCESS".equals(result.get("return_code").toString()) && "SUCCESS".equals(result.get("result_code").toString())) {
            lbbMemberTradeMapper.updateByPrimaryKeySelective(trade);
            String desc = "您申请的{money}提现审核成功！";
            String money = new BigDecimal(trade.getAmount()).divide(new BigDecimal(100)).setScale(2).toString();
            desc = desc.replace("{money}", money);

            walletService.notice2(trade, "提现通知", desc);
            return Callback.success("2002", "转账成功");
        } else {
            // 当返回错误码为“SYSTEMERROR”时，请不要更换商户订单号，一定要使用原商户订单号重试，否则可能造成重复支付等资金风险。
            return Callback.fail("2001", "转账失败:" + result.get("return_msg").toString() + result.get("err_code_des"));
        }

    }

    /**
     * 支付宝自动转账
     **/

    public JsonData staffPayByZfb(Long id, String userid, String mark) throws AlipayApiException {
        LbbMemberTrade trade = lbbMemberTradeMapper.selectByPrimaryKey(id);

        trade.setRemittance(2);
        trade.setPayStaff(userid);
        trade.setPayType(2);
        trade.setStatus(Success);
        trade.setNote(mark);
        BigDecimal i = new BigDecimal(trade.getAmount());
        i = i.divide(new BigDecimal(100), 2, BigDecimal.ROUND_DOWN);
        Map<String, Object> map = JSON.parseObject(trade.getContent());
        AlipayClient alipayClient = new DefaultAlipayClient(ALI_URL, ALI_APP_ID, ALI_PRIVATE_KEY, PayConstants.FORMAT, PayConstants.CHARSET, ALI_PUBLIC_KEY, PayConstants.SIGN_TYPE);
        AlipayFundTransToaccountTransferRequest request = new AlipayFundTransToaccountTransferRequest();
        request.setBizContent("{" +
                "    \"out_biz_no\":\"" + trade.getTradeNo() + "\"," +
                "    \"payee_type\":\"ALIPAY_LOGONID\"," +
                "    \"payee_account\":\"" + map.get("alipay") + "\"," +
                "    \"amount\":\"" + i + "\"," +
                "\"payee_real_name\":\"" + map.get("alipayname") + "\"," +
                "    \"payer_show_name\":\"咸鱼\"," +
                "    \"remark\":\"" + mark + "\"," +
                "  }");
        AlipayFundTransToaccountTransferResponse response = alipayClient.execute(request);
        if (response.isSuccess()) {

            trade.setTradeTime(new Date());
            lbbMemberTradeMapper.updateByPrimaryKeySelective(trade);

            String desc = "您申请的{money}提现审核成功！";
            String money = i.toString();
            desc = desc.replace("{money}", money);

            walletService.notice2(trade, "提现通知", desc);
            return Callback.success("200", "转账成功", null);
        } else {
            boolean ii = this.getTradeNoStatus(trade.getTradeNo());
            if (ii) {

                trade.setTradeTime(new Date());
                String desc = "您申请的{money}提现审核成功！";
                String money = i.toString();
                desc = desc.replace("{money}", money);

                walletService.notice2(trade, "提现通知", desc);
                lbbMemberTradeMapper.updateByPrimaryKeySelective(trade);
                return Callback.success("200", "转账成功", null);
            } else {
                return Callback.fail("200", response.getSubMsg(), null);
            }
        }
    }

    /**
     * 人工转账
     **/
    public int staffPayByartificial(Long id, String userid) {
        LbbMemberTrade trade = lbbMemberTradeMapper.selectByPrimaryKey(id);
        if (!trade.getStatus().equals(Empty)) {
            return 0;
        }
        trade.setRemittance(2);
        trade.setPayStaff(userid);
        trade.setPayType(1);
        trade.setStatus(Success);
        trade.setMethod(3);

        trade.setTradeTime(new Date());
        String desc = "您申请的{money}提现审核成功！";
        String money = new BigDecimal(trade.getAmount()).divide(new BigDecimal(100)).setScale(2).toString();
        desc = desc.replace("{money}", money);

        walletService.notice2(trade, "提现通知", desc);
        return lbbMemberTradeMapper.updateByPrimaryKeySelective(trade);
    }

    /**
     * 查询转账订单状态
     **/
    public boolean getTradeNoStatus(String tradeNo) throws AlipayApiException {
        AlipayClient alipayClient = new DefaultAlipayClient(PayConstants.ALI_URL, PayConstants.ALI_APP_ID, PayConstants.ALI_PRIVATE_KEY, PayConstants.FORMAT, PayConstants.CHARSET, PayConstants.ALI_PUBLIC_KEY, PayConstants.SIGN_TYPE);
        AlipayFundTransOrderQueryRequest request = new AlipayFundTransOrderQueryRequest();
        request.setBizContent("{" +
                "    \"out_biz_no\":\"" + tradeNo + "\"," +
                "  }");
        AlipayFundTransOrderQueryResponse response = alipayClient.execute(request);
        if (response.isSuccess()) {
            log.info("调用成功");
            return true;
        } else {
            return false;
        }
    }



    public List<LbbMemberTrade> selectByExample(LbbMemberTradeExample example) {
        return lbbMemberTradeMapper.selectByExample(example);
    }




    /**
     * 用户增加收入并且通知用户方法计入排行榜
     *
     * @param memberId      用户id
     * @param amount        金额 单位:分
     * @param title         标题
     * @param remark        备注
     * @param orderId       订单号
     * @param requestHeader 头部参数
     * @param content       其他内容
     * @param moneyCategory 计算类型
     *                      * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public int addMoney(String memberId, int amount, String title, String remark,
                        String orderId, RequestHeaders requestHeader, String content, MoneyCategory moneyCategory) {
        LbbMemberTrade trade = new LbbMemberTrade();
        trade.setCreateTime(new Date());
        trade.setModifyTime(new Date());
        trade.setHasDeleted(Booleans.False.name());
        trade.setOrderId(orderId);
        trade.setMemberId(memberId);
        trade.setAppId("xianyu");
        trade.setAppStore(requestHeader.getAppStore());
        trade.setVersion(requestHeader.getVersion());
        trade.setTitle(title);
        trade.setAmount(amount);
        trade.setExtra(0);
        trade.setRemark(remark);
        trade.setCategory(TradeCategory.Income);
        trade.setType(RewardType.Cash);
        trade.setStatus(Success);
        trade.setOs(requestHeader.getOs());
        trade.setOsv(requestHeader.getOsv());
        trade.setIpAddr(requestHeader.getIpAddr());
        trade.setMacAddr(requestHeader.getMacAddr());
        trade.setImei(requestHeader.getImei());
        trade.setTradeTime(new Date());
        if (moneyCategory.getIsRank().equals(Whether.YES)) {
            rankingService.memberAddScore(memberId, amount);
        }
        this.addInWallet(memberId, amount);
        this.addRecord(trade, moneyCategory, requestHeader);
        return lbbMemberTradeMapper.insertSelective(trade);

    }

    /**
     * 加入新的统计表
     *
     * @param trade
     * @param moneyCategory
     */
    private void addRecord(LbbMemberTrade trade, MoneyCategory moneyCategory,RequestHeaders headers) {
        try {
            MemberNewTrade newTrade = new MemberNewTrade();
            newTrade.setCreateTime(LocalDateTime.now());
            newTrade.setMemberId(trade.getMemberId());
            newTrade.setAppStore(trade.getAppStore());
            newTrade.setVersion(trade.getVersion());
            newTrade.setRemark(trade.getRemark());
            newTrade.setIpAddr(trade.getIpAddr());
            newTrade.setMacAddr(trade.getMacAddr());
            newTrade.setImei(trade.getImei());
            newTrade.setCategory(moneyCategory.getTaskCategory().name());
            newTrade.setCategoryTitle(moneyCategory.getTaskCategory().getTitle());
            newTrade.setType(RewardType.Cash.getIndex());
            newTrade.setTimeMillis(System.currentTimeMillis());
            newTrade.setAmount(new BigDecimal(trade.getAmount()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_DOWN));
            newTrade.setMyAmount(moneyCategory.getMyMoney());
            LocalDateTime time = lbbMemberMapper.selectCreaTimeByMemberId(trade.getMemberId());
            if (time != null) {
                if (LocalDate.now().equals(time.toLocalDate())) {
                    newTrade.setIsNewMember(Whether.YES.getDbIndex());
                } else {
                    newTrade.setIsNewMember(Whether.NO.getDbIndex());
                }
            } else {
                newTrade.setIsNewMember(-1);
            }
          //  iMemberNewTradeMongodb.insert(newTrade);
            memberNewTradeMapper.insertSelective(newTrade);
            int k=redisClient.hincrby(CATEGORY_KEY+moneyCategory.getTaskCategory().name()+":"+
                    LocalDate.now().format(DateTimeFormatter.ISO_DATE),trade.getMemberId(),1L).intValue();
            redisClient.hincrby(CATEGORY_KEY+"ALL:"+
                    LocalDate.now().format(DateTimeFormatter.ISO_DATE),trade.getMemberId(),1L);
            rouseDayConfigService.endRecord(moneyCategory.getTaskCategory(),k,headers);
        } catch (Exception e) {
            log.error("记录报记录出错602");
            e.printStackTrace();
        }
    }

    private static final String ALL_CASH_MONEY_KEY = "WALLET:ALL_CASH_MONEY";
    private static final String ALL_MONEY_KEY = "WALLET:ALL_MONEY";

    /**
     * 加载累计提现 存在才增加 否则等待用户调用钱包初始化以后才能增加
     *
     * @param memberId
     * @param amount
     */
//    public void addInCashRedis(String memberId, Integer amount) {
//        boolean has = redisClient.hexists(ALL_CASH_MONEY_KEY, memberId);
//        if (has) {
//            redisClient.hincrby(ALL_CASH_MONEY_KEY, memberId, (long) amount);
//        }
//    }
//
    /**
     * 加载累计总收益 存在才增加 否则等待用户调用钱包初始化以后才能增加
     *
     * @param memberId
     * @param amount
     */
    public void addInWallet(String memberId, int amount) {
//        boolean has = redisClient.hexists(ALL_MONEY_KEY, memberId);
//        if (has) {
//            redisClient.hincrby(ALL_MONEY_KEY, memberId, (long) amount);
//        }
        try {
            memberWalletService.incomeMoney(memberId,amount);
        }catch (Exception e){
            memberWalletService.initData(memberId);
        }

    }



    /**
     * 清除用户redis的缓存
     *
     * @param memberId
     */
    public void walletClean(String memberId) {
        memberWalletMapper.deleteByPrimaryKey(memberId);
        memberWalletService.initData(memberId);
    }



    public int checkincome(List<String> list) {
        return lbbMemberTradeMapper.checkIncomeById(list);
    }

    public LbbMemberTrade selectById(Long id) {
        return lbbMemberTradeMapper.selectByPrimaryKey(id);
    }

    public int updateTrade(LbbMemberTrade trade) {
        return lbbMemberTradeMapper.updateByPrimaryKeySelective(trade);
    }


}
